package com.abel.bigwater.kmgw.impl

import com.abel.bigwater.dataserver.model.FlowDataPojo
import com.abel.bigwater.dataserver.model.PojoHelper.COL_FLOW_DATA
import com.abel.bigwater.dataserver.model.PojoHelper.KEY_RECV_TIME
import com.abel.bigwater.dataserver.model.PojoHelper.KEY_SEND_COUNT
import com.abel.bigwater.dataserver.model.PojoHelper.KEY_SEND_TIME
import com.abel.bigwater.dataserver.model.PojoHelper.KEY_START_TIME
import com.abel.bigwater.dataserver.model.PojoHelper.KEY_STATION
import com.abel.bigwater.kmgw.dao.FlowDao
import com.mongodb.client.result.DeleteResult
import org.joda.time.DateTime
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.Update
import org.springframework.data.mongodb.core.query.isEqualTo
import org.springframework.stereotype.Repository
import java.util.*

@Repository
class FlowDaoImpl : FlowDao {

    @Autowired
    var mongoTemplate: MongoTemplate? = null

    override fun saveFlowData(fd: FlowDataPojo, colName: String?) {
        if (colName == null) {
            mongoTemplate?.save(fd)
        } else {
            mongoTemplate?.save(fd, colName)
        }
    }

    /**
     * update if exists; insert if not.
     */
    override fun upsert(fd: FlowDataPojo, colName: String?): Long? {
        val dl: DeleteResult?
        if (colName == null) {
            dl = mongoTemplate?.remove(Query().addCriteria(
                    Criteria.where(KEY_STATION).isEqualTo(fd.station)
                            .and(KEY_START_TIME).isEqualTo(fd.startTime)),
                    FlowDataPojo::class.java)
            mongoTemplate?.save(fd)
        } else {
            dl = mongoTemplate?.remove(Query().addCriteria(
                    Criteria.where(KEY_STATION).isEqualTo(fd.station)
                            .and(KEY_START_TIME).isEqualTo(fd.startTime)),
                    FlowDataPojo::class.java, colName)
            mongoTemplate?.save(fd, colName)
        }

        return if (dl == null) 1 else 1 + dl.deletedCount
    }

    override fun listFlowData(query: Query): MutableList<FlowDataPojo>? {
        return mongoTemplate?.find(query, FlowDataPojo::class.java)
    }

    /**
     * update and return count (may be 0 or 1)
     */
    override fun updateSendCount(fd: FlowDataPojo): Long {
        val ur = mongoTemplate?.updateFirst(Query().addCriteria(
                Criteria.where(KEY_STATION).isEqualTo(fd.station)
                        .and(KEY_START_TIME).isEqualTo(fd.startTime)),
                Update.update(KEY_SEND_COUNT, fd.sendCount),
                FlowDataPojo::class.java)

        return ur?.modifiedCount ?: 0
    }

    /**
     * remove specified flow.
     */
    override fun removeFlowData(fd: FlowDataPojo): Long {
        val dr = mongoTemplate?.remove(Query().addCriteria(
                Criteria.where(KEY_STATION).isEqualTo(fd.station)
                        .and(KEY_START_TIME).isEqualTo(fd.startTime)),
                FlowDataPojo::class.java)
        return dr?.deletedCount ?: 0
    }

    /**
     * 删除 daysBefore 以前的数据.
     */
    override fun removeExpired(daysBefore: Int): Long? {
        val qry = Query()
        qry.addCriteria(Criteria.where(KEY_RECV_TIME).lt(DateTime.now().minusDays(daysBefore).toDate()))
        return mongoTemplate?.remove(qry, FlowDataPojo::class.java, COL_FLOW_DATA)?.deletedCount
    }

    /**
     * mark as 'sent' - they are not sent again.
     */
    override fun markSent(fd: FlowDataPojo): Long? {
        val ur = mongoTemplate?.updateFirst(Query().addCriteria(Criteria
                .where(KEY_STATION).isEqualTo(fd.station)
                .and(KEY_START_TIME).isEqualTo(fd.startTime)),
                Update.update(KEY_SEND_TIME, Date()),
                FlowDataPojo::class.java)

        return ur?.modifiedCount ?: 0
    }

    /**
     * fetch unsent in days - send them out then.
     */
    override fun unsentList(days: Int): MutableList<FlowDataPojo>? {
        return mongoTemplate?.find(Query().addCriteria(Criteria
                .where(KEY_SEND_TIME).`is`(null)
                .and(KEY_SEND_COUNT).lt(3)),
                FlowDataPojo::class.java)
    }

}